<?php
/**
 * Created by PhpStorm.
 * User: longli
 * VX: isa1589518286
 * Date: 2019/08/09
 * Time: 16:46
 * @link http://www.lmterp.cn
 */

namespace app\common\library\socket;

use Closure;
use Co;

/**
 * swoole 操作 socket 客户端
 * Class Client
 * @package app\common\library\socket
 */
class Client
{
    /**
     * 连接地址
     * @var string
     */
    protected $url = "";

    /**
     * 端口号
     * @var int
     */
    protected $port;

    /**
     * 连接地址
     * @var string
     */
    protected $uri = "/";

    /**
     * 是否保持长连接
     * @var bool
     */
    protected $keepAlive = true;

    /**
     * 睡眠的秒数
     * @var float
     */
    protected $sleep = 0;

    /**
     * 当客户端没有数据推送时，默认睡眠秒数
     * @var int
     */
    protected $emptyDataSleep = 0;

    public function __construct($url, $port, $uri = "/", $keepAlive = true)
    {
        $this->url = $url;
        $this->port = $port;
        $this->uri = $uri;
        $this->keepAlive = $keepAlive;

        Co::set([
            'max_coroutine' => PHP_INT_MAX,
            'log_level' => SWOOLE_LOG_INFO,
            'trace_flags' => 0
        ]);
    }

    /**
     * @param Closure|array|string $fn 发送消息
     * @date 2019/08/12
     * @author longli
     */
    public function send($fn)
    {
        Co::create(function() use($fn)
        {
            $cli = new \Swoole\Coroutine\Http\Client($this->getUrl(), $this->getPort());
            $cli->upgrade($this->getUri());
            $sleep = $this->getSleep();
            $keepAlive = $this->isKeepAlive();
            do
            {
                $msg = is_callable($fn)
                    ? call_user_func($fn, $cli)
                    : $fn;
                if($msg === false) break;
                if(empty($msg))
                {
                    // 发送心跳包，保持连接
                    $cli->push("");
                    if($this->emptyDataSleep > 0) Co::sleep($this->emptyDataSleep);
                    continue;
                }
                if(is_array($msg)) $msg = json_encode($msg);
                $cli->push($msg);
                if($keepAlive && $sleep > 0) Co::sleep($sleep);
            }while($keepAlive);
            $cli->close();
        });
    }

    /**
     * @return string
     */
    public function getUrl()
    {
        return $this->url;
    }

    /**
     * @param string $url
     */
    public function setUrl($url)
    {
        $this->url = $url;
    }

    /**
     * @return int
     */
    public function getPort()
    {
        return $this->port;
    }

    /**
     * @param int $port
     */
    public function setPort($port)
    {
        $this->port = $port;
    }

    /**
     * @return string
     */
    public function getUri()
    {
        return $this->uri;
    }

    /**
     * @param string $uri
     */
    public function setUri($uri)
    {
        $this->uri = $uri;
    }

    /**
     * @return bool
     */
    public function isKeepAlive()
    {
        return $this->keepAlive;
    }

    /**
     * @param bool $keepAlive
     */
    public function setKeepAlive($keepAlive)
    {
        $this->keepAlive = $keepAlive;
    }

    /**
     * @return float
     */
    public function getSleep()
    {
        return $this->sleep;
    }

    /**
     * @param float $sleep
     */
    public function setSleep($sleep)
    {
        $this->sleep = $sleep;
    }

    /**
     * @param int $emptyDataSleep
     */
    public function setEmptyDataSleep($emptyDataSleep)
    {
        $this->emptyDataSleep = $emptyDataSleep;
    }

    /**
     * @return int
     */
    public function getEmptyDataSleep()
    {
        return $this->emptyDataSleep;
    }
}